using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Catastrophe.AutoSulution.EDC
{
	public class CheckOuts
	{
		/// <summary>
		/// CRC16校验
		/// </summary>
		/// <param name="byteAry">字节数组</param>
		/// <returns></returns>
		public static byte[] Crc16(byte[] byteAry)
		{
			byte b = byte.MaxValue;
			byte b2 = byte.MaxValue;
			byte b3 = 1;
			byte b4 = 160;
			for (int i = 0; i < byteAry.Length; i++)
			{
				b = (byte)(b ^ byteAry[i]);
				for (int j = 0; j <= 7; j++)
				{
					byte b5 = b2;
					byte b6 = b;
					b2 = (byte)(b2 >> 1);
					b = (byte)(b >> 1);
					if ((b5 & 1) == 1)
					{
						b = (byte)(b | 0x80u);
					}
					if ((b6 & 1) == 1)
					{
						b2 = (byte)(b2 ^ b4);
						b = (byte)(b ^ b3);
					}
				}
			}
			return new byte[2] { b, b2 };
		}

		/// <summary>
		///     求和校验
		/// </summary>
		/// <param name="byteAry">字节数组</param>
		public static byte[] Sum(byte[] byteAry)
		{
			List<byte> list = new List<byte>();
			list.AddRange(byteAry);
			list.AddRange(Encoding.ASCII.GetBytes(CheckOuts.CheckSum(list.ToArray()).ToString("X").PadLeft(2, '0')));
			return list.ToArray();
		}

		/// <summary>
		///     求和校验
		/// </summary>
		/// <param name="byteAry">字节数组</param>
		/// <returns></returns>
		public static byte CheckSum(byte[] byteAry)
		{
			int num = byteAry.Aggregate(0, (int current, byte t) => current + t);
			return (byte)num;
		}

		/// <summary>
		///     CC校验求和取反，+1，取后两位16进制数
		/// </summary>
		/// <param name="byteAry">字节数组</param>
		/// <returns></returns>
		public static byte CheckCc(byte[] byteAry)
		{
			int num = byteAry.Aggregate(0, (int current, byte t) => current + t);
			num = ~num;
			num++;
			byte[] bytes = BitConverter.GetBytes(num);
			return bytes[0];
		}

		/// <summary>
		///     从某位开始求和
		/// </summary>
		/// <param name="byteAry">字节数组</param>
		/// <param name="start">起始</param>
		/// <returns></returns>
		public static byte CheckSum(byte[] byteAry, int start)
		{
			int num = 0;
			for (int i = start; i <= byteAry.Length - start + 1; i++)
			{
				num += byteAry[i];
			}
			return (byte)num;
		}

		/// <summary>
		///     bcc
		/// </summary>
		/// <param name="byteAry">字节数组</param>
		/// <param name="len">长度</param>
		/// <returns></returns>
		public static byte Get_CheckXor(byte[] byteAry, int len)
		{
			byte b = 0;
			for (int i = 0; i < len; i++)
			{
				b = (byte)(b ^ byteAry[i]);
			}
			return b;
		}

		/// <summary>
		/// 小数比较相等-放大以后比较整数
		/// </summary>
		/// <param name="value1">数值1</param>
		/// <param name="value2">数值2</param>
		/// <param name="digital">比较位数</param>
		/// <returns></returns>
		public static bool DecimalEqual1(double value1, double value2, int digital = 3)
		{
			double num = Math.Pow(10.0, digital);
			return (int)(Math.Round(value1, digital) * num) == (int)(Math.Round(value2, digital) * num);
		}

		/// <summary>
		/// 小数比较大小-放大以后比较整数
		/// </summary>
		/// <param name="value1">数值1</param>
		/// <param name="value2">数值2</param>
		/// <param name="digital">比较位数</param>
		/// <returns></returns>
		public static int DecimalCompare(double value1, double value2, int digital = 3)
		{
			double num = Math.Pow(10.0, digital);
			return (int)(Math.Round(value1, digital) * num) - (int)(Math.Round(value2, digital) * num);
		}

		/// <summary>
		/// 用compareTo比较
		/// </summary>
		/// <param name="value1">数值1</param>
		/// <param name="value2">数值2</param>
		/// <returns></returns>
		public static int DecimalCompareTo(double value1, double value2)
		{
			return value1.CompareTo(value2);
		}

		/// <summary>
		/// 小数比较
		/// </summary>
		/// <param name="value1">数值1</param>
		/// <param name="value2">数值2</param>
		/// <param name="precision">精确</param>
		/// <returns></returns>
		public static bool DecimalEqual2(double value1, double value2, double precision = 1E-05)
		{
			return Math.Abs(value1 - value2) < precision;
		}

		/// <summary>
		/// n次取值中只要一次等于目标值则返回目标值否则原值不变
		/// </summary>
		/// <param name="value">取值源</param>
		/// <param name="dstValue">目标值判断</param>
		/// <param name="list">装载n次集合</param>
		/// <param name="times">默认判断次数</param>
		/// <returns>是否达到判断次数</returns>
		public static bool GetNOnce(ref dynamic value, dynamic dstValue, ref List<dynamic> list, int times = 10)
		{
			if (list == null)
			{
				list = new List<object>();
			}
			((List<object>)list).Add(value);
			if (list.Count == times)
			{
				if (list.Any((dynamic x) => x.Equals(dstValue)))
				{
					value = dstValue;
				}
				list.Clear();
				return true;
			}
			return false;
		}
	}
}
